#include <stdio.h>
#include <unistd.h>
#include <linux/fb.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/ioctl.h>

typedef unsigned short color_t; /* 根据实际情况修改，此处为unsigned short是565的屏 */

static struct fb_var_screeninfo __g_vinfo; /* 显示信息 */
static color_t *__gp_frame; /* 虚拟屏幕首地址 */

int framebuffer_init(void) {
	int fd = 0;
	fd = open("/dev/fb1", O_RDWR);
	if (fd == -1) {
		perror("fail to open /dev/fb1\n");
		return -1;
	}

	ioctl(fd, FBIOGET_VSCREENINFO, &__g_vinfo); /* 获取显示信息 */
	printf("bits_per_pixel = %d\n", __g_vinfo.bits_per_pixel); /* 一个像素点对应的位数，如果值为16则为565格式输出，如果值为32则为888格式输出 */
	printf("xres_virtual = %d\n", __g_vinfo.xres_virtual); /* 虚拟x轴像素点数 */
	printf("yres_virtual = %d\n", __g_vinfo.yres_virtual); /* 虚拟y轴像素点数 */
	printf("xres = %d\n", __g_vinfo.xres); /* x轴像素点数 */
	printf("yres = %d\n", __g_vinfo.yres); /* y轴像素点数 */

	__gp_frame = mmap(NULL, /* 映射区的开始地址，为NULL表示由系统决定映射区的起始地址 */
			__g_vinfo.xres_virtual * __g_vinfo.yres_virtual
					* __g_vinfo.bits_per_pixel / 8, /* 映射区大小 */
			PROT_WRITE | PROT_READ, /* 内存保护标志（可读可写） */
			MAP_SHARED, /* 映射对象类型（与其他进程共享） */
			fd, /* 有效的文件描述符 */
			0); /* 被映射内容的偏移量 */
	if (__gp_frame == NULL) {
		perror("fail to mmap\n");
		return -1;
	}
	return 0;
}

void full_screen(color_t color) {
	int i;
	color_t *p = __gp_frame;

	for (i = 0; i < __g_vinfo.xres_virtual * __g_vinfo.yres_virtual; i++) {
		*p++ = color;
	}
}

int main() {
	if (framebuffer_init()) {
		return -1;
	}

//red 	    1111 1000 0000 0000
//green 	0000 0111 1110 0000
//blue      0000 0000 0001 1111

	unsigned int red = 0xF800;
	unsigned int green = 0x07E0;
	unsigned int blue = 0x001F;

	while (1) {
		full_screen(red);
		sleep(4);
		full_screen(green);
		sleep(4);
		full_screen(blue);
		sleep(4);
		full_screen(red | green);
		sleep(4);
		full_screen(red | green | blue);
		sleep(4);
		full_screen(0);
		sleep(4);
	}
	return 0;
}

